<!--
 * Copyright (C) 2013 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
-->
<!DOCTYPE html>
<html>
<head>
   <title>Async Test.</title>
  <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
</head>
<body>
  <script type="text/javascript">
    goog.require('goog.net.Cookies');
    goog.require('goog.net.XhrIo');
    goog.require('goog.testing.MockControl');
    goog.require('goog.testing.jsunit');
    goog.require('goog.testing.mockmatchers');

    function setUp() {
      headers = new goog.structs.Map();
      mockControl = new goog.testing.MockControl();
      stringMatcher = goog.testing.mockmatchers.isString;
      functionMatcher = goog.testing.mockmatchers.isFunction;
      objectMatcher = goog.testing.mockmatchers.isObject;
    }

    function tearDown() {
      mockControl.$tearDown();
      headers.clear();
    }

  /**
   * Verifies that static send function is invoked.
   */
  function testStaticSendFunction() {
    var timeoutInterval = 500;
    var callback = function() {};
    var postParams = 'bar=barParam&foo=fooParam';
    var headers = {'X-Some-Header': 'My XMLHttpRequest'};
    var preparedHeaders;

    mockControl.createMethodMock(goog.net.XhrIo, 'send');
    goog.net.XhrIo.send(
        stringMatcher, functionMatcher, stringMatcher,
        postParams, objectMatcher, timeoutInterval).$does(
            function(u, c, m, pp, headers, t) {
              preparedHeaders = headers;
            });
    mockControl.$replayAll();
    try {
      treasury.async.XhrIo.send(
          'foo/', callback, 'POST', postParams, headers, timeoutInterval);
      assertEquals('Expect ' + 'X-Requested-With',
          preparedHeaders.get('X-Requested-With'), 'XMLHttpRequest');
      assertFalse('Expect no ' + 'X-CSRFToken',
          !!preparedHeaders.get('X-CSRFToken'));
      assertTrue('Expect ' + 'X-Some-Header',
          !!preparedHeaders.get('X-Some-Header'));
    } finally {
      mockControl.$tearDown();
    }
  }

  /**
   * Verifies that the instance function is invoked for POST request.
   */
  function testCsrfProtectForPostRequest() {
    setUpMockCsrfCookies('test');
    mockControl.$replayAll();
    try {
        treasury.async.XhrIo.csrfProtect(headers, 'foo/', 'POST');
        assertEquals(headers.get('X-CSRFToken'), 'test');
    } finally {
      mockControl.$verifyAll();
    }
  }

  /**
   * Verifies that the instance function is invoked for a PUT request.
   */
  function testCsrfProtectForPutRequest() {
     setUpMockCsrfCookies('test');
     mockControl.$replayAll();
    try {
        treasury.async.XhrIo.csrfProtect(headers, 'foo/', 'PUT');
        assertEquals(headers.get('X-CSRFToken'), 'test');
    } finally {
      mockControl.$verifyAll();
    }
  }

/**
   * Verifies that the instance function is invoked for delete request.
   */
  function testCsrfProtectForDeleteRequest() {
    setUpMockCsrfCookies('test');
     mockControl.$replayAll();
    try {
        treasury.async.XhrIo.csrfProtect(headers, 'foo/', 'DELETE');
        assertEquals(headers.get('X-CSRFToken'), 'test');
    } finally {
      mockControl.$verifyAll();
    }
  }

  /** Verifies that the instance function is invoked for a head request. */
  function testCsrfProtectForHeadRequest() {
    treasury.async.XhrIo.csrfProtect(headers, 'foo/', 'HEAD');
    assertUndefined(headers.get('X-CSRFToken'));
  }

  /**
   * Verifies that the instance function is invoked for a GET request.
   */
  function testCsrfProtectForGetRequest() {
    treasury.async.XhrIo.csrfProtect(headers, 'foo/', 'GET');
    assertUndefined(headers.get('X-CSRFToken'));
  }

  /**
   * Verifies that the instance function is invoked for a TRACE request.
   */
  function testCsrfProtectForTraceRequest() {
    treasury.async.XhrIo.csrfProtect(headers, 'foo/', 'TRACE');
    assertUndefined(headers.get('X-CSRFToken'));
  }

  /**
   * Verifies that the instance function is invoked for OPTIONS request.
   */
  function testCsrfProtectForOptionsRequest() {
    treasury.async.XhrIo.csrfProtect('foo/', 'OPTIONS');
    assertUndefined(headers.get('X-CSRFToken'));
  }

  /**
   * Mocks the cookie set up. The expectations' replay is the responsibility of
   * the invoking method.
   *
   * @param {string} cookieValue value of the cookie to be set.
   */
  function setUpMockCsrfCookies(cookieValue) {
    var mockCookieInstance = mockControl.createStrictMock(goog.net.Cookies);
    var mockCookieConstructor =
        mockControl.createConstructorMock(goog.net, 'Cookies');
    mockCookieConstructor(objectMatcher).$returns(mockCookieInstance);
    if (cookieValue) {
      mockCookieInstance.get('csrftoken').$returns(cookieValue);
    }
  }
</script>
</body>
</html>